#pragma once
#include <string>
using std::wstring;

class Args
{
public:
	Args();
	~Args();

#define DEFINE_ARGS_PUT(type) Args& put(type)
#define DEFINE_ARGS_GET(type) Args& get(type&)

public:
	/*
	 * Gets the address of m_data in hexadecimal
	 */
	wstring toString() const;
	/*
	 * Switches the current read pointer to extended data (external, one-way operation)
	 */
	Args& extend();
	/*
	 * Puts a value into m_data
	 */
	DEFINE_ARGS_PUT(void*);
	DEFINE_ARGS_PUT(bool);
	DEFINE_ARGS_PUT(char);
	DEFINE_ARGS_PUT(unsigned char);
	DEFINE_ARGS_PUT(short);
	DEFINE_ARGS_PUT(unsigned short);
	DEFINE_ARGS_PUT(int);
	DEFINE_ARGS_PUT(unsigned int);
	DEFINE_ARGS_PUT(float);
	DEFINE_ARGS_PUT(double);
	DEFINE_ARGS_PUT(long long);
	DEFINE_ARGS_PUT(unsigned long long);
	DEFINE_ARGS_PUT(const wstring&);
	/*
	 * Gets a value from m_data or m_ext depends on extended switch
	 */
	DEFINE_ARGS_GET(void*);
	DEFINE_ARGS_GET(bool);
	DEFINE_ARGS_GET(char);
	DEFINE_ARGS_GET(unsigned char);
	DEFINE_ARGS_GET(short);
	DEFINE_ARGS_GET(unsigned short);
	DEFINE_ARGS_GET(int);
	DEFINE_ARGS_GET(unsigned int);
	DEFINE_ARGS_GET(float);
	DEFINE_ARGS_GET(double);
	DEFINE_ARGS_GET(long long);
	DEFINE_ARGS_GET(unsigned long long);
	DEFINE_ARGS_GET(wstring);

private:
	void ensureCapacity(size_t increment);

private:
	size_t m_len; // length of data
	void* m_data; // data
	void* m_ext; // extended data (external)
	void* m_wos; // current pos of writer
	void* m_ros; // current pos of reader
};
